home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Developers / src / menu-slide-11-p / MenuSlide / MenuSlide.p < prev    next >
Encoding:
Text File  |  1994-11-23  |  6.4 KB  |  306 lines  |  [TEXT/PJMM]

  1. program MenuSlide;
  2.  
  3. {    Original concept and design by Hugh.Fisher@anu.edu.au                         }
  4. {    Code to find right edge of application menus contributed by                    }
  5. { Matthew Axsom (chewey@nesw.MV.COM) }
  6.  
  7. {    Written using THINK Pascal 4.0                                                            }
  8.  
  9. {    Have a look at the accompanying MenuSlide.txt file if you didn't see    }
  10. {    the original posting about what it does and why. "These things            }
  11. {    will become clear to you...at least, clearer than they are at                }
  12. {    the moment" - Slartibartfast in HHG to the G                                        }
  13.  
  14. {    Feel free to use this code for whatever purpose you like. If you can     }
  15. {    write an INIT/cdev that would work for all applications, please do!     }
  16.  
  17. const
  18. {    Private event codes that I use    }
  19.     suspendEvent = 12;
  20.     resumeEvent = 13;
  21.     motionEvent = 14;
  22.  
  23.     MBarHeightAddr = $0BAA;
  24.  
  25. {    The menus are mostly non-functional, but we need them to demonstrate    }
  26.     kAppleMenu = 128;
  27.     kFileMenu = 129;
  28.     kEditMenu = 130;
  29.     kOtherMenu = 131;
  30.  
  31.     cQuit = 9;    { File menu - this command really works }
  32.  
  33. var
  34.     myWindow: WindowPtr;
  35.     myText: Handle;
  36.  
  37. procedure handleMousePress (event: EventRecord);
  38. forward;
  39.  
  40. procedure mouseInMenu (event: EventRecord);
  41. forward;
  42.  
  43. procedure handleWindowUpdate (event: EventRecord);
  44. forward;
  45.  
  46. procedure handleSuspend (event: EventRecord);
  47. forward;
  48. procedure handleResume (event: EventRecord);
  49. forward;
  50.  
  51. procedure ExitApp;
  52. forward;
  53.  
  54. { Mathew's code, translated from C }
  55.  
  56. const
  57.     LMMenuListAddr = $0A1C;
  58.  
  59. type
  60.     MenuRec = record
  61.             mh: MenuHandle;
  62.             startLeft: Integer;
  63.         end;
  64.     MenuRecPtr = ^MenuRec;
  65.     MenuRecHand = ^MenuRecPtr;
  66.  
  67.     MenuListRec = record
  68.             size: Integer; { div sizeof(MenuRec) for number of items }
  69.             nextLeft: Integer; { Where next edge will go }
  70.             filler: Integer;
  71.             item: array[0..0] of MenuRec; { List of menus }
  72.         end;
  73.     MenuListPtr = ^MenuListRec;
  74.     MenuListHand = ^MenuListPtr;
  75.  
  76. function MBarRightEdge: Integer;
  77.     var
  78.         p: ^MenuListHand;
  79.         list: MenuListHand;
  80.     begin
  81.     p := pointer(LMMenuListAddr);
  82.     list := p^;
  83.     MBarRightEdge := list^^.nextLeft;
  84.     end;
  85.  
  86. (****        Sliding the menu bar        ****)
  87.  
  88. function MBarHeight: Integer;
  89.     var
  90.         p: ^Integer;
  91.     begin
  92.     p := pointer(MBarHeightAddr);
  93.     MBarHeight := p^;
  94.     end;
  95.  
  96. procedure slideMenuOff;
  97.     var
  98.         savePort, desktop: GrafPtr;
  99.         rightEdge, step: Integer;
  100.         source, dest: Rect;
  101.         saveGray, menuBox: RgnHandle;
  102.         now: LongInt;
  103.     begin
  104. { Look at low memory menu list to work out where right edge of application menus is }
  105.     rightEdge := MBarRightEdge;
  106. { Need to fool around with the desktop. This is similar to hiding the menu bar. }
  107.     GetWMgrPort(desktop);
  108.     saveGray := NewRgn;
  109.     CopyRgn(GetGrayRgn, saveGray);
  110.     SetRect(source, 0, 0, screenBits.bounds.right, MBarHeight);
  111.     menuBox := NewRgn;
  112.     RectRgn(menuBox, source);
  113.     UnionRgn(GetGrayRgn, menuBox, GetGrayRgn);
  114. { OK, now scroll the menu off the screen }
  115.     SetRect(source, 0, 0, rightEdge, MBarHeight);
  116.     dest := source;
  117.     step := 1;
  118.     while (dest.right > 0) do
  119.         begin
  120.         OffsetRect(dest, -step, 0);
  121.         CopyBits(desktop^.portBits, desktop^.portBits, source, dest, srcCopy, nil);
  122. { Wait a tick }
  123.         now := TickCount;
  124.         while now = TickCount do
  125.             ;
  126.         step := step * 2;
  127.         end;
  128. { And put things back }
  129.     CopyRgn(saveGray, GetGrayRgn);
  130.     DisposeRgn(saveGray);
  131.     DisposeRgn(menuBox);
  132.     end;
  133.  
  134. (****    Menu handling    ****)
  135.  
  136. procedure handleMousePress (event: EventRecord);
  137.     var
  138.         part: Integer;
  139.         clickWindow: WindowPtr;
  140.         savePort: GrafPtr;
  141.     begin
  142.     part := FindWindow(event.where, clickWindow);
  143.     if part = inSysWindow then
  144.         SystemClick(event, clickWindow)
  145.     else if part = inMenuBar then
  146.         mouseInMenu(event)
  147.     end;
  148.  
  149. procedure mouseInMenu (event: EventRecord);
  150.     var
  151.         choice: LongInt;
  152.         menuID, itemID: Integer;
  153.     var
  154.         itemText: Str255;
  155.         err: OSErr;
  156.     begin
  157.     choice := MenuSelect(event.where);
  158.     menuID := HiWord(choice);
  159.     itemID := LoWord(choice);
  160.     if menuID > 0 then
  161.         begin
  162.         if menuID = kAppleMenu then
  163.             begin
  164.             GetItem(GetMenu(kAppleMenu), itemID, itemText);
  165.             err := OpenDeskAcc(itemText);
  166.             end
  167.         else if menuID = kFileMenu then
  168.             begin
  169.             if itemID = cQuit then
  170.                 ExitApp;
  171.             end;
  172.         end;
  173.     HiliteMenu(0);
  174.     end;
  175.  
  176. (****    Window handling    ****)
  177.  
  178. procedure handleWindowUpdate (event: EventRecord);
  179.     var
  180.         box: Rect;
  181.     begin
  182.     if event.message = LongInt(myWindow) then
  183.         begin
  184.         box := myWindow^.portRect;
  185.         InsetRect(box, 16, 16);
  186.         TextBox(myText^, GetHandleSize(myText), box, TEJustLeft);
  187.         ValidRect(myWindow^.portRect);
  188.         end;
  189.     end;
  190.  
  191. (****    Top level event handling    ****)
  192.  
  193. procedure handleSuspend (event: EventRecord);
  194.     begin
  195.     slideMenuOff;
  196.     end;
  197.  
  198. procedure handleResume (event: EventRecord);
  199.     begin
  200.     end;
  201.  
  202. procedure decodeOSEvent (event: EventRecord);
  203.     var
  204.         kind, flag: LongInt;
  205.     begin
  206.     kind := BitAnd(BitShift(event.message, -24), $0FF);
  207.     flag := BitAnd(event.message, $01);
  208.     if kind = suspendResumeMessage then
  209.         begin
  210.         if flag = 0 then
  211.             begin
  212.             event.what := suspendEvent;
  213.             handleSuspend(event);
  214.             end
  215.         else if flag = 1 then
  216.             begin
  217.             event.what := resumeEvent;
  218.             handleResume(event);
  219.             end;
  220.         end;
  221.     end;
  222.  
  223. procedure handleNextEvent;
  224.     var
  225.         event: EventRecord;
  226.         savePort: GrafPtr;
  227.         w: WindowPtr;
  228.     begin
  229.     if WaitNextEvent(everyEvent, event, 0, nil) then
  230.         begin
  231.         if event.what = mouseDown then
  232.             handleMousePress(event)
  233.         else if event.what = updateEvt then
  234.             begin
  235.             GetPort(savePort);
  236.             w := WindowPtr(event.message);
  237.             SetPort(w);
  238.             BeginUpdate(w);
  239.             handleWindowUpdate(event);
  240.             EndUpdate(w);
  241.             SetPort(savePort);
  242.             end
  243.         else if event.what = osEvt then
  244.             decodeOSEvent(event);
  245.         end;
  246.     end;
  247.  
  248. (****    Toolbox ritual incantations for starting and finishing    ****)
  249.  
  250. procedure initToolbox;
  251.     var
  252.         event: EventRecord;
  253.     begin
  254.     InitGraf(@thePort);
  255.     InitFonts;
  256.     InitWindows;
  257.     InitMenus;
  258.     TEInit;
  259.     InitDialogs(nil);
  260.     SetEventMask(everyEvent);
  261.     FlushEvents(everyEvent, 0);
  262.     InitCursor;
  263.     end;
  264.  
  265. procedure exitApp;
  266.     begin
  267.     ExitToShell;
  268.     end;
  269.  
  270. procedure openWindow;
  271.     var
  272.         bounds: Rect;
  273.     begin
  274. { Give ourself a window }
  275.     bounds.left := (screenBits.bounds.right - screenBits.bounds.left - 480) div 2;
  276.     bounds.right := bounds.left + 480;
  277.     bounds.top := 64;
  278.     bounds.bottom := bounds.top + 240;
  279.     myWindow := NewWindow(nil, bounds, 'Menu Slide', true, PlainDBox, WindowPtr(-1), False, 0);
  280.     SetPort(myWindow);
  281. { Dig text for display out of resource fork }
  282.     myText := GetResource('TEXT', 128);
  283.     HLock(myText);
  284.     end;
  285.  
  286. procedure createMenus;
  287.     var
  288.         m: MenuHandle;
  289.     begin
  290.     m := GetMenu(kAppleMenu);
  291.     AddResMenu(m, 'DRVR');
  292.     InsertMenu(m, 0);
  293.     InsertMenu(GetMenu(kFileMenu), 0);
  294.     InsertMenu(GetMenu(kEditMenu), 0);
  295.     InsertMenu(GetMenu(kOtherMenu), 0);
  296.     DrawMenuBar;
  297.     end;
  298.  
  299. begin
  300. initToolbox;
  301. openWindow;
  302. createMenus;
  303. while true do
  304.     handleNextEvent;
  305. exitApp;
  306. end.